/**
 * 整个项目会用到的一些工具方法定义
 */
import {
	getAppId
} from "./platform.js"
import request_ from './request.js'
import globalData from "./globalData.js"
import {
	baseUrl,
	api_url,
	APP_APPID
} from "./constant"
import {
	eventBus
} from "./eventPublishSubscribe"
import {
	sha256
} from 'js-sha256'
import {
	goLogin
} from "../main.js"

export const request = request_;
/**
 * 错误的统一处理方法，可方便后续做错误监控
 * @param {boolean} letUserKnow : 是否toast让用户知晓
 */
export const errHandler = (err, letUserKnow = false) => {
	if (letUserKnow) {
		const str = typeof err === "string" ? err : JSON.stringify(err)

		console.error('错误统一处理函数', str);
		if (!str.length) {
			return false;
		}
		uni.showToast({
			title: str,
			icon: "none",
		})
	} else {
		// eslint-disable-next-line
		console.error(err);
	}
}

/**
 * 获取到在App.vue文件中所定义的globalData对象数据
 * @param {string} key: 要获取globalData中的哪个值
 */

export const getGlobalData = (key) => {
	const globalObj = getApp().globalData || {}
	return globalObj[key]
}
//开始加载：把方法存到缓存中执行
export const getShowLoading = (obj) => {
	if (getGlobalData("showLoading")) {
		getGlobalData("showLoading")(obj)
	} else {
		let showLoading = uni.showLoading
		setGlobalData("showLoading", showLoading)
		uni.showLoading(obj)
	}
}
//结束加载：把方法存到缓存中执行
export const getHideLoading = () => {
	if (getGlobalData("hideLoading")) {
		getGlobalData("hideLoading")()
	} else {
		let hideLoading = uni.hideLoading
		setGlobalData("hideLoading", hideLoading)
		uni.hideLoading()
	}
}

//公共登录方法
export const commonAlipayLogin = () => {
	uni.login({
		provider: 'alipay',
		success: function(loginRes) {
			console.log('===111=是是是111===', loginRes);
			request("member/mall/aliPay/user/alipayLogin", {
					// avatar: (infoRes.userInfo.avatarUrl || '/static/0.png'),
					// nickName: (infoRes.userInfo.nickName || '默认用户'),
					authCode: loginRes.authCode,
					source: '1',
				}, "POST")
				.then((res) => {
					let userDetail = (res && res.data) || {}
					let uid = userDetail.uid
					saveUserId(uid)
					saveZWZUserDetail(userDetail)
				})
			return
			// 获取用户信息
			uni.getUserInfo({
				provider: 'alipay',
				success: function(infoRes) {
					infoRes.response = JSON.parse(infoRes.response)
					console.log('支付宝小程序的静默登录信息111111111111111', infoRes);
					if (!loginRes.authCode) {
						return false;
					}
					request("member/mall/aliPay/user/alipayLogin", {
							// avatar: (infoRes.userInfo.avatarUrl || '/static/0.png'),
							// nickName: (infoRes.userInfo.nickName || '默认用户'),
							authCode: loginRes.authCode,
							source: '1',

						}, "POST")
						.then((res) => {
							let userDetail = (res && res.data) || {}
							let uid = userDetail.uid
							saveUserId(uid)
							saveZWZUserDetail(userDetail)
							memberCardIntegral()

							saveUserVisitScene()
						})
				},
				fail: (res) => {
					if (loginRes.authCode) {
						request("member/mall/aliPay/user/exemptLogin", {
							avatar: '/static/0.png',
							nickName: '默认用户',
							authCode: loginRes.authCode
						}, "POST").then((res) => {
							let userDetail = (res && res.data) || {}
							let uid = userDetail.uid
							saveUserId(uid)
							saveZWZUserDetail(userDetail)
							memberCardIntegral()

							saveUserVisitScene()
						})
					}
				}
			});

		}
	});
}

//我的页面获取会员卡，积分，商家折扣数据
export const memberCardIntegral = () => {
	request("member/mall/aliPay/user/getinfo", {
			shopid: getZWZUserDetail().shopId,
			uid: getZWZUserDetail().uid,
		}, "POST")
		.then((res) => {
			let userDetail = (res && res.data) || {}
			saveMemberDetail(userDetail)
		})
}
// export const saveUserVisitScene = () => {
// 	if (getScene() != undefined) {
// 		request("member/mall/aliPay/userVisitCode/addUserVisitCode", {
// 			'uid': getUserId(),
// 			'code': getScene()
// 		}, "POST").then((res) => {
// 			console.log(res);
// 		})
// 	}
// }




export const getErrText = (val) => {
	uni.setStorageSync('wuliIsNone', 'true')
}

/**
 * 设置全局数据某个key的值
 * @param {string} key: 要设置的key
 * @param {any} val: 要设置的值
 */
export const setGlobalData = (key, val) => {
	if (!key) {
		// eslint-disable-next-line no-console
		return
	}
	const globalObj = getApp().globalData || {}
	globalObj[key] = val
}

/**
 * 删掉存储在全局的某个数据，避免一直占用内存
 * @param {*} key
 */
export const delGlobalData = (key) => {
	if (!key) return
	const globalObj = getApp().globalData || {}
	delete globalObj[key]
}

/**
 * 保存租物租平台的用户详情信息，通过登录接口获取到的
 */
export const saveZWZUserDetail = (userVo) => {
	setStorageExpensive("zwzUserDetail", userVo)
}


/**
 * 我的页面---会员卡，积分，商家折扣
 */
export const saveMemberDetail = (userVo) => {
	setStorageExpensive("memberDetail", userVo)
}

/**
 * 将值保存到localStorage中，同时缓存一份数据到全局
 * 所以说，只有十分必要的数据存localStorage，否则直接利用setGlobalData存全局即可
 * 注：和getStorageCheap搭配使用
 * @param {*} k
 * @param {*} v
 */
export const setStorageExpensive = (k, v) => {
	setGlobalData(k, v)
	uni.setStorageSync(k, v)
}

/**
 * 空间换时间，全局取不到就从localStorage中取，然后在进行缓存
 * 注：同一个key必须搭配setStorageExpensive进行使用，否则可能缓存值可能过时了
 */
export const getStorageCheap = (key) => {
	const cacheVal = getGlobalData(key)
	if (cacheVal != undefined) return cacheVal // 内存中具有缓存值
	// 否则再从localStorage同步取
	const val = uni.getStorageSync(key)
	setGlobalData(key, val) // 取完后缓存到内存，那么下次再取就无需从localStorage中取，而是取的缓存
	return val
}

/**
 * 获取租物租平台的用户详情信息
 */
export const getZWZUserDetail = () => {
	return getStorageCheap("zwzUserDetail")
}

/**
 * 获取我的页面-会员卡，商家折扣，积分全局数据
 */
export const getMemberDetail = () => {
	return getStorageCheap("memberDetail")
}

/**
 * 获取用户ID
 */
export const getUserId = () => {
	var uid_fb = uni.getStorageSync('uid_fb')
	if (uid_fb) {
		return uid_fb;
	}
	return getStorageCheap("uid");
}



/**
 * 获取用户手机号
 */
export const getUserTel = () => {
	var tel_fb = uni.getStorageSync('tel_fb')
	if (tel_fb) {
		return tel_fb;
	}
	return getStorageCheap("tel");
}

/**
 * 获取用户额度
 */
export const getUserBalance = () => {
	var isBalance_num = uni.getStorageSync('isBalance_num')
	if (isBalance_num) {
		return isBalance_num;
	}
	return getStorageCheap("isBalance");
}


/**
 * 获取用户isReceive（是否有领取过额度0：没有  1：领取过）
 */
export const getUserReceive = () => {
	var isReceive_num = uni.getStorageSync('isReceive_num')
	if (isReceive_num) {
		return isReceive_num;
	}
	return getStorageCheap("isReceive");
}

// 保存用户购物额度
export const saveUserBalance = (val) => {
	setStorageExpensive("isBalance", val)
	uni.setStorageSync('isBalance_num', val);
}

/**
 * 保存用户ID
 */
export const saveUserId = (val) => {
	// val="2270cc98c0bfe2de5c52291bda418dcb81981998hkm20xykn0fb" 
	//uid存储到内容中减少api调用
	setStorageExpensive("uid", val)
	uni.setStorageSync('uid_fb', val);
}


/**
 * 保存用户手机号
 */
export const saveUserTel = (val) => {
	setStorageExpensive("tel", val)
	uni.setStorageSync('tel_fb', val);
}

/**
 * 保存用户isReceive（是否有领取过额度0：没有  1：领取过）
 */
export const saveUserReceive = (val) => {
	// val="2270cc98c0bfe2de5c52291bda418dcb81981998hkm20xykn0fb" 
	//uid存储到内容中减少api调用
	setStorageExpensive("isReceive", val)
	uni.setStorageSync('isReceive_num', val);
}


/**
 * 保存会员状态
 */
export const saveVipType = (val) => {
	setStorageExpensive("viptype", val)
	uni.setStorageSync('viptype', val);
}
/**
 * 获取会员状态值
 */
export const getVipType = () => {
	var viptype = uni.getStorageSync('viptype')
	if (viptype) {
		return viptype;
	}
	return getStorageCheap("viptype");
}


/**
 * 保存场景值
 */
export const saveScene = (val) => {
	setStorageExpensive("scene", val)
	uni.setStorageSync('scene', val);
}
/**
 * 获取场景值
 */
export const getScene = () => {
	console.log('scene' + getStorageCheap("scene"))
	var scene = uni.getStorageSync('scene')
	if (scene) {
		return scene;
	}
	return getStorageCheap("scene");
}



/**
 * 保存clickid
 */

export const saveClickId = (val) => {
	setStorageExpensive("clickid", val)
	uni.setStorageSync('clickid', val);
}

/**
 * 获取clickid
 */
export const getClickId = () => {
	var clickid = uni.getStorageSync('clickid')
	if (clickid) {
		return clickid;
	}
	return getStorageCheap("clickid");
}
export const getTenantId = () => {
	request('order/mall/components/getTenantIDByAppletAppId')
		.then((res) => {
			uni.setStorage({
				key: 'tenantId',
				data: res.data
			});
		});
}
/**
 * 支付宝登录的处理方法。就仅仅只是为了获取到用户的uid而言，采用静默授权和主动授权都是一样可以达到用处；
 * 但是如果想要获取到用户更多的信息的话，那么则必须使用主动授权。对于租物租平台的登录而言，后端只用了授权码去查uid。所以使用
 * @params {bool} isSilence : 是否不显示弹窗来获取用户的authCode
 * @params {Object} data : 传参数据
 * @params {Function} cb : 登录之后的调用方法
 */
const alipayLogin = (isSilence, data, cb, showToast) => {

	// #ifndef MP-ALIPAY
	request(baseUrl + "/api/Json_login.php", {
			uid: getUserId()
		}, "POST")
		.then((res) => {
			const userDetail = (res && res.data) || {}
			const uid = userDetail.uid
			saveUserId(uid)
			saveZWZUserDetail(userDetail)
			eventBus && eventBus.emit("successLoginThenReFetch")
		})
	return false;
	// #endif

	const scope = isSilence ? "auth_base" : "auth_user"
	my.getAuthCode({
		scopes: [scope],
		success: (res) => {
			const {
				authCode
			} = res
			if (!authCode) {
				uni.showToast({
					title: "获取授权码失败",
					icon: "none"
				})
				return
			}
			showToast && uni.showLoading({
				title: "登录中",
				mask: true
			})
			const postData = {
				...data,
				authCode
			}
			request("member/mall/aliPay/user/exemptLogin", postData, "POST")
				.then((res) => {
					const userDetail = (res && res.data) || {}
					const uid = userDetail.uid
					saveUserId(uid)
					saveZWZUserDetail(userDetail)
					eventBus && eventBus.emit("successLoginThenReFetch")
				})
				.catch((err) => {
					errHandler(err)
				})
				.finally(() => {
					// 万一登录接口出现问题，功能降级也支持用户浏览其它内容
					showToast && uni.hideLoading()
					cb && cb()
				})
		},
	})
}

/**
 * 登录的处理方法，先获取到用户在宿主平台的authCode，然后后端会利用这个authCode生成租物租平台的uId
 * @params {bool} isSilence : 是否采用静默授权，默认采用静默授权
 * @params {Object} data : 调用登录接口传的额外参数
 * @params {Function} cb : 登录成功之后的回调方法
 * @params {bool} refresh : 是否强制更新
 * @params {bool} showToast : 是否需要显示登录弹窗
 */
export const loginHandler = (
	isSilence = true,
	data = {},
	cb,
	refresh = false,
	showToast = true,
) => {
	const savedUid = getUserId() // 本地保存的用户ID，不能保证百分百有效，失效情况得在request中拦截
	if (savedUid && !refresh) {
		// 已存在的话就不显式登录了
		cb && cb()
		return
	}

	// #ifdef MP-ALIPAY
	return alipayLogin(isSilence, data, cb, showToast)
	// #endif
}

//支付宝小程序跳转 switchType:判断是否跳转tabBar

/**
 * 进行页面跳转的处理方法
 * @param {String} url : 需要跳转的页面地址
 * @param {Boolean} switchType : 判断是否跳转tabBar
 * @param {Boolean} useReplace : 是否采用覆盖形式进行跳转
 */
export const onAlipayTo = (url, switchType, useReplace = false) => {

	if (url.indexOf('pages') === 0) { //原程序部分页面前面没有加 斜杆 补上
		url = '/' + url;
	}
	if (url.indexOf("alipays://") === 0) {
		if (url.indexOf("http") !== -1) {
			let paths = decodeURIComponent(url.replace(/.+(?=https)/, ""))
			//h5链接跳转
			my.ap.navigateToAlipayPage({
				path: paths,
			})
			return
		}
		let decodeUrl = decodeURIComponent(url).replace(/.+(?=appId)/, "")
		let urls = decodeUrl.split("&page=")
		let appId = urls[0].split("=")[1]
		let path = urls[1]
		//小程序之间跳转
		uni.navigateToMiniProgram({
			appId,
			path,
		})
	} else if (switchType) {
		uni.switchTab({
			url,
		})
	} else {
		// 常规路径跳转
		const jumpFun = useReplace ? uni.redirectTo : uni.navigateTo
		jumpFun({
			url
		})
	}
}

/**
 * LOG: 部分支付宝账号可能不存在昵称
 * 判断本地是否有会员基础信息数据，会员基础信息文档：https://opendocs.alipay.com/mini/introduce/twn8vq
 */
export const checkHasUserBasicInfo = () => {
	const userObj = getZWZUserDetail()
	const {
		avatar,
		nickName
	} = userObj // 比较重要的就是这两个字段
	return avatar || nickName
	// return !!(avatar && nickName)
}
/**
 * 判断本地是否有手机号
 */
export const checkHasPhone = () => {
	const userObj = getZWZUserDetail()
	const {
		telephone
	} = userObj // 比较重要的就是这两个字段
	return !!telephone
}
/**
 * 检查进入页面时，是否缺失了页面的某部分关键参数
 * @param {Object} obj : 要进行检查的对象
 * @param {Array} checkKeys : 非必传，要检查这个对象的哪些字段参数
 * @return {Boolean} : true表示缺少了关键参数
 */
export const checkIsPageLessParameter = (obj, checkKeys) => {
	const checkFailedAction = () => {
		uni.showModal({
			title: "提示",
			content: "缺少关键参数，请尝试重新进入页面",
			showCancel: false,
			success: function() {
				uni.switchTab({
					url: "/pages/index/index"
				})
			},
		})
	}
	if (!obj || Object.prototype.toString.call(obj) !== "[object Object]") {
		checkFailedAction()
		return true
	}

	if (
		!checkKeys ||
		Object.prototype.toString.call(checkKeys) !== "[object Array]" ||
		!checkKeys.length
	) {
		if (obj == undefined) { // 简单判断即可
			checkFailedAction()
			return true
		}
		return false
	}

	const isEverythingOk = checkKeys.every((k) => obj[k] != undefined)
	if (!isEverythingOk) {
		checkFailedAction()
		return true
	}
	return false
}

/**
 * 对时间字符串进行格式处理
 * @param {*} str
 * @param {*} fmt
 * @returns
 */
export const formatStrDate = (str, fmt) => {
	const o = {
		"y+": str.slice(0, 4),
		"M+": str.slice(5, 7),
		"d+": str.slice(8, 10),
		"h+": str.slice(11, 13),
		"m+": str.slice(14, 16),
		"s+": str.slice(17, 19),
	}

	if (/(y+)/.test(fmt))
		fmt = fmt.replace(
			RegExp.$1,
			(str.slice(0, 4) + "").substr(4 - RegExp.$1.length)
		)
	for (let k in o) {
		if (new RegExp(`(${k})`).test(fmt)) {
			fmt = fmt.replace(
				RegExp.$1,
				RegExp.$1.length === 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length)
			)
		}
	}
	return fmt
}

/**
 * 进行文件上传
 * @param {string} url : 图片资源的本地链接
 */
export const fileUploadHandler = (url, F = function() {}) => {
	if (!url) {
		errHandler("上传时找不到文件", true)
		return Promise.reject()
	}
	// 请求认证签名
	let timestamp = new Date().getTime();
	let appid = "hy_60b60e38711abe9f";
	let appSecret = "6160aa57cd9a3dbc8229ce92f9e41810b8104f6518f740f9";
	let sourceStr = appid + "," + timestamp + "," + appSecret;
	let sign = sha256(sourceStr);
	const upload = (filePath) => {
		return uni.uploadFile({
			url: `${baseUrl}order/mall/components/uploadFile`,
			fileType: "image", // 仅仅只有支付宝小程序是必传的
			filePath: filePath,
			name: "multipartFile",
			fileName: "multipartFile",
			formData: {},
			header: {
				// #ifndef H5
				"Content-Type": "application/x-www-form-urlencoded",
				// #endif
				"appids": appid,
				"timestamps": timestamp,
				"signs": sign,
				"appletappid": APP_APPID
			},
			success: (res) => {
				F(res);
			}
		})
	}
	// #ifdef H5
	return upload(url);
	// #endif
	// #ifndef H5
	return uni.compressImage({
		src: url,
		quality: 80,
		success: res => {
			console.log('after compressImage tempFilePath:', res.tempFilePath)
			upload(res.tempFilePath);
		}
	})
	// #endif
}
/**
 * 判断是否进行实名认证
 * @param {Boolean} justCheckIdNum : 是否只需要检查身份证号码；如果只需要检查身份证号码的话，那么则认为有身份证号码即完成实名认证；否则不仅得检查身份证号码，还得检查图片
 */
export const checkHasShiMingRenZheng = (justCheckIdNum = false) => {
	if (!getUserId()) {
		return Promise.reject('未登录');
	}
	return request(
		"member/mall/userCertification/getDesensitizationByUid", {},
		"GET",
		true
	).then((res) => {
		const vo = res.data || {}
		let checkKeys = ["idCard"] // 身份证号必检查
		if (!justCheckIdNum) { // 不仅仅只要检查身份证号的话，那么也得检查身份证图片
			checkKeys = checkKeys.concat(["idCardBackUrl", "idCardFrontUrl"])
		}

		const checkResult = checkKeys.every((n) => vo[n] != undefined)

		const obj = {
			idCard: vo["idCard"],
			checkResult,
			isReceive: vo["isReceive"]
		}
		return obj
	})
}

// 校验失败时的弹窗
export const failVerifyToast = cn => {
	const tip = cn ? `请输入${cn}` : "请填写所有参数在提交"
	uni.showToast({
		title: tip,
		icon: "none",
	})
}

/**
 * 传参的检查守卫，过滤掉空值，注意这里的校验，赞不支持复杂校验规则，只支持校验非空
 * @param {Object} data : 要进行校验检查的数据
 * @param {Object} cnMapObj : 字段的中英文对照
 * @param {Boolean} ignoreEmptyString : 判断是否需要过滤空字符串，传true代表空字符串也是有效的，默认认为空字符串是无效数据
 * @param {Boolean} hideToast : 是否需要隐藏弹窗，传true的话，参数校验失败并不会弹窗
 * @param {Array} checkKeys : 需要校验的键名列表
 * @param {Function} toastCb : 弹窗的提示方法
 */
export const postDataGuard = (
	data,
	cnMapObj,
	ignoreEmptyString = false,
	hideToast = false,
	checkKeys,
	toastCb = failVerifyToast
) => {

	if (!data) {
		!hideToast && toastCb && toastCb()
		return {
			postData: {},
			status: false
		}
	}
	const keys = Object.keys(data)

	let checkKeyList = checkKeys // 需要检查的键名集合
	if (Object.prototype.toString.call(checkKeys) !== "[object Array]") {
		// 没有传入checkKeys，或者传入参数无效的话，那么默认检查对象的所有键名
		checkKeyList = keys
	}

	const newObj = {} // 该方法加工之后的数据，加工之后会把空值给过滤掉
	let passStatus = true // 校验状态，默认校验完成
	let failedKey = "" // 第一个校验失败的键名

	keys.forEach((key) => {
		const val = data[key]
		if (checkKeyList.includes(key)) {
			// 是待检查的键名
			if (val == undefined) {
				// 检查失败
				passStatus = false
			} else if (val == "" && !ignoreEmptyString) {
				// 检查失败：值为空字符串，且需要忽略掉空字符串
				passStatus = false
			} else if (
				Object.prototype.toString.call(val) === "[object Array]" &&
				!val.length
			) {
				// 检查失败：是数组数据类型，而且是一个空数组
				passStatus = false
			} else {
				// 检查通过，将值挂载到newObj上面
				newObj[key] = val
			}

			if (!passStatus) {
				!failedKey && (failedKey = key) // 提示第一个校验失败的
			}
		} else {
			// 无需进行检查的键
			val != undefined && (newObj[key] =
				val) // 哪怕无需检查，也应该过滤掉传参中的undefined、null；空字符串、0、false继续保留其在后端都有对应的意思
		}
	})

	if (!passStatus) {
		// const cn = cnMapObj?.[failedKey]
		// !hideToast && toastCb && toastCb(cn)
	}

	return {
		postData: newObj,
		pass: passStatus,
	}
}

/**
 * 和下面均参考自：https://hehuiyun.github.io/2020/10/10/%E5%85%B3%E4%BA%8EJS%E5%B0%8F%E6%95%B0%E7%9A%84%E5%8A%A0%E5%87%8F%E4%B9%98%E9%99%A4%E7%B2%BE%E5%BA%A6%E4%B8%A2%E5%A4%B1%E9%97%AE%E9%A2%98/
 * 先将小数化为整数，然后在进行加法操作，避免丢失精度
 * @param {*} arg1
 * @param {*} arg2
 * @returns
 */
export const makeAdd = (arg1, arg2) => {
	let r1, r2, m
	try {
		r1 = arg1.toString().split(".")[1].length
	} catch (e) {
		r1 = 0
	}
	try {
		r2 = arg2.toString().split(".")[1].length
	} catch (e) {
		r2 = 0
	}
	m = Math.pow(10, Math.max(r1, r2))
	return (arg1 * m + arg2 * m) / m
}

// 进行减法操作
export const makeSub = (arg1, arg2) => {
	let r1, r2, m
	try {
		r1 = arg1.toString().split(".")[1].length
	} catch (e) {
		r1 = 0
	}
	try {
		r2 = arg2.toString().split(".")[1].length
	} catch (e) {
		r2 = 0
	}
	m = Math.pow(10, Math.max(r1, r2))
	const v = (arg1 * m - arg2 * m) / m
	return v >= 0 ? v : 0
}

/**
 * 返回地址对象的字符串描述
 * 使用场景：归还页面、地址选择页面
 * @param {Object} addressObj : 地址对象
 */
export const getAddressDescStr = (addressObj) => {
	if (Object.prototype.toString.call(addressObj) !== "[object Object]")
		return ""
	const {
		provinceStr = "",
			cityStr = "",
			areaStr = "",
			street = "",
	} = addressObj
	return `${provinceStr}${cityStr}${areaStr}${street}`
}

/**
 * 为空时避免显示成undefined
 * @param {any} val 需要显示的，可能为空的值
 * @param {string} placeholder : 你希望的缺省占位符
 * @param {string} prefix : 前缀
 * @param {boolean} force : 是否需要强制进行校验
 * @returns string
 */
export const uiStr = (val, placeholder, prefix = "", force = false) => {
	if (val == undefined) {
		return placeholder || ""
	}
	const str = `${val}`
	const xiaoshu = str.split(".")[1] || ""
	if ((prefix == "¥" || force) && xiaoshu.length <= 1) { // 金额类，且小数点不足两位
		val = val.toFixed(2)
	}
	return `${prefix}${val}`
}

/**
 * 返回一个时间字符串的时间戳表示
 * @param {*} dateStr
 * @returns
 */
export const getDateValueOf = (dateStr) => {
	let dateObj
	if (!dateStr) {
		// 如果没传的化，默认取现在时间
		dateObj = new Date()
	} else {
		dateObj = new Date(dateStr.replace(/-/g, "/"))
	}

	return [
		dateObj.valueOf(),
		dateObj.getFullYear(),
		dateObj.getMonth() + 1,
		dateObj.getDate(),
	]
}

/**
 * 获取商品的运费中文表述
 * @param {Object} obj : 商品对象
 */
export const getProductYunfeiText = obj => {
	const placholder = "-"
	if (Object.prototype.toString.call(obj) !== "[object Object]") return placholder
	const {
		returnfreightType,
		freightType
	} = obj
	const returnUIMap = {
		FREE: "归还用户支付",
		PAY: "归还商家承担",
	} // 归还时的中文对照

	const fahuoUIMap = {
		FREE: "发货商家包邮",
		PAY: "发货到付",
		SELF: "发货用户自提",
	} // 发货时的中文对照
	const part1 = fahuoUIMap[freightType] || ""
	const part2 = returnUIMap[returnfreightType] || ""

	let result = []
	result.push(part1)
	result.push(part2)

	result = result.filter(n => !!n) // 过滤无效值
	return result.join("/") || placholder
}

/**
 * 判断商品是否显示买断，以及是否支持提前买断
 * 1:可以提前买断。2:支持到期买断 0:不可以买断
 * @param {Object} obj : 商品对象
 * @return {Object} { canMaiduan: boolean, canBefore: boolean }，是否可以买断、是否可以提前买断
 */
export const returnProductMaiduanStatus = obj => {
	if (Object.prototype.toString.call(obj) !== "[object Object]") return {
		canMaiduan: false,
		canBefore: false,
	}
	const {
		buyOutSupport
	} = obj
	if (buyOutSupport == 0) {
		return {
			canMaiduan: false,
			canBefore: false,
		}
	} else if (buyOutSupport == 2) {
		return {
			canMaiduan: true,
			canBefore: false,
		}
	} else if (buyOutSupport == 1) {
		return {
			canMaiduan: true,
			canBefore: true,
		}
	} else {
		return {
			canMaiduan: false,
			canBefore: false,
		}
	}
}

/**
 * 获取channelID数据
 * @returns
 */
export const returnChannelId = () => {
	const infoObj = globalData.infoByAppId || {}
	const appDescObj = infoObj[getAppId()] || {}
	return appDescObj.channelId
}

/**
 * 获取页面参数，分享场景通过onload参数会获取不到，得从页面栈中读取数据进行获取才行
 * @param {*} options 
 * @param {*} key 
 */
export const getPageParams = (options, key) => {
	if (options) {
		return options[key]
	} else {
		const params = getCurrentPages()[0].options
		return params[key] || ""
	}
}



export const go_Myl = (res, data, is_go = true) => {
	let isIos = uni.getSystemInfoSync().platform
	// #ifdef APP-PLUS  
	if (res.status !== '01' && res.signState === false && res.signUrl) { //订单列表拉起扫脸 需要特殊处理 构建数据
		//APP打开蚂蚁链签署1
		plus.runtime.openURL(res.signUrl)
	}
	// #endif
	// #ifdef H5
	if (res.status !== '01' && res.signState === false && res.signUrl) { //订单列表拉起扫脸 需要特殊处理 构建数据
		if (isIos == 'ios') {
			uni.showLoading({
				title: "加载中"
			})
			let timer = null
			timer = setTimeout(() => {
				uni.hideLoading()
				window.open(res.signUrl)
				clearTimeout(timer);
				timer = null
			}, 300); // 延迟0.5秒
		} else {
			window.open(res.signUrl)
		}
	}
	// #endif

	// #ifdef MP-ALIPAY
	if (res.signUrl.indexOf('alipays') === 0) {
		var pages = {}
		// debugger
		pages.page = res.signUrl.split("&");
		pages.app = pages.page[0].split("=");
		pages.app_ = res.signUrl.split("&page=");
		console.log('pages/signH5/index?signUrl=' + decodeURIComponent(pages.app_[1]).split("signUrl=")[1],
			32331231232132);
		console.log('pages/signH5/index?signUrl=' + decodeURIComponent(pages.app_[1]), 99999999999999999);
		console.log(res.signUrl.indexOf("signUrl"), 989899889898);
		if (res.signUrl.indexOf("signUrl") > -1) {
			my.navigateToMiniProgram({ //支付宝小程序
				appId: pages.app[1],
				path: 'pages/signH5/index?signUrl=' + decodeURIComponent(pages.app_[1]).split("signUrl=")[
					1],
				success: (res) => {
					console.log(JSON.stringify(res))
				},
				fail: (res) => {
					console.log(JSON.stringify(res))
				}
			});
		}
	}
	// #endif
	uni.hideLoading()
}



//新更新的
export const go_Myl11 = (res, data, is_go = true) => {
	console.log('go_Myl res', res);
	console.log('go_Myl data', data);
	console.log('go_Myl is_go', is_go);

	// #ifdef APP-PLUS  
	if (res.status !== '01' && res.signState === false && res.signUrl) { //订单列表拉起扫脸 需要特殊处理 构建数据
		// res.data = {}
		// res.data.signatoryUrl = res.signUrl;
		//APP打开蚂蚁链签署
		plus.runtime.openURL(res.signUrl)
	}
	// #endif

	// #ifndef APP-PLUS 
	if (res.status !== '01' && res.signState === false && res.signUrl) { //订单列表拉起扫脸 需要特殊处理 构建数据
		res.data = {}
		res.data.signatoryUrl = res.signUrl;
	}
	// alipays://platformapi/startapp?appId=2021004108689505&page=pages/home/index&query=serveEnv%3Drelease%26agreementEntityType%3DBUYER%26agreementBizNo%3DPROD231022000000959504
	if (res.data.signatoryUrl.indexOf('alipays') === 0) {
		var pages = {}
		// debugger
		pages.page = res.data.signatoryUrl.split("&");
		pages.app = pages.page[0].split("=");
		pages.app_ = res.data.signatoryUrl.split("&page=");
		console.log('pages/signH5/index?signUrl=' + decodeURIComponent(pages.app_[1]).split("signUrl=")[1],
			32331231232132);
		console.log('pages/signH5/index?signUrl=' + decodeURIComponent(pages.app_[1]), 99999999999999999);
		console.log(res.data.signatoryUrl.indexOf("signUrl"), 989899889898);
		if (res.data.signatoryUrl.indexOf("signUrl") > -1) {
			my.navigateToMiniProgram({ //支付宝小程序
				appId: pages.app[1],
				path: 'pages/signH5/index?signUrl=' + decodeURIComponent(pages.app_[1]).split("signUrl=")[
					1],
				success: (res) => {
					console.log(JSON.stringify(res))
				},
				fail: (res) => {
					console.log(JSON.stringify(res))
				}
			});
		} else {
			const {
				params
			} = schemeToParams(res.data.signatoryUrl);
			if (res.data.signatoryUrl && params) {
				const {
					appId,
					path,
					query,
					...extraData
				} = params;
				my.navigateToMiniProgram({
					query,
					extraData,
					appId,
					path,
					success: () => {},
					fail: () => {},
				});
			}
		}
	} else {
		//// #ifdef MP-ALIPAY
		//支付宝小程序打开蚂蚁链签署
		plus.runtime.openURL(res.data.signatoryUrl)
		//// #endif
		//// #ifndef APP-PLUS
		uni.redirectTo({
			url: "/pagesOther/xieyi/web?url=" + encodeURIComponent(res.data.signatoryUrl)
		});
		//// #endif
	}
	// #endif	
	uni.hideLoading()
}















export const go_EQian = (res, data, is_go = true) => {
	let isIosEnv = uni.getSystemInfoSync().platform
	if (res.status !== '01' && res.signState === false && res.esignUrl) { //订单列表拉起扫脸 需要特殊处理 构建数据
		res.data = {}
		res.data.signatoryUrl = res.esignUrl;
	}
	if (res.data.signatoryUrl.indexOf('esign.cn')) {
		if (res.plugEsignUrl) {
			// plugEsignUrl  为支付宝小程序封装好的跳转路径
			my.navigateTo({
				// url: "plugin://esign/esign?env=sml&flowId=4c355b36fdd8428d8662a5da30ad35fe&signerId=084d1d2095b14d878eeda51d5e32f121&skipResult=true&skipGuide=true"
				// env=${sml}=======sml - 沙箱模拟环境
				// prod - 正式生产环境
				url: res.plugEsignUrl
			})
		} else { // APP和微信走的接口

			// #ifndef MP-ALIPAY || H5    
			plus.runtime.openURL(res.data.signatoryUrl)
			// #endif
			// #ifdef MP-ALIPAY   

			uni.showToast({
				title: '请联系商家客服签署合同',
				icon: 'none'
			})
			// #endif	
			// #ifdef H5 
			if (isIosEnv == 'ios') {
				uni.showLoading({
					title: "加载中"
				})
				let timer1 = null
				timer1 = setTimeout(() => {
					uni.hideLoading()
					window.open(res.data.signatoryUrl, "_blank");
					clearTimeout(timer1);
					timer1 = null
				}, 300); // 延迟0.5秒
			} else {
				window.open(res.data.signatoryUrl, "_blank");
			}

			// #endif	
		}
	} else {}

}

export const getReq = (url) => {
	let req = new Object()
	if (url.indexOf("?") != -1) {
		let str = url.split("?")[1],
			strs = str.split("&");
		for (let i = 0; i < strs.length; i++) {
			req[strs[i].split("=")[0]] = unescape(strs[i].split("=")[1])
		}
	}
	return req
}

export const userChannel = (user = "", option = {}) => {
	let link = "";
	let wxpid = null;
	// #ifdef APP-PLUS
	link = plus.runtime.arguments;
	// #endif

	// #ifdef MP-WEIXIN
	const query = option.query || {};
	wxpid = query.pid;
	// #endif

	// #ifdef H5
	link = window.location.hash;
	// #endif

	const reqArguments = getReq(link);
	const rentchannelid = uni.getStorageSync("pid");
	const pid = reqArguments.pid || rentchannelid || wxpid;
	if (!!pid) {
		uni.setStorageSync("pid", pid)
		const uid = user || getUserId();
		if (!!uid) {
			request("member/mall/aliPay/user/userChannel", {
					uid,
					pid
				}, "POST")
				.then((res) => {})
		}
	}
	if (!!reqArguments.productId) {
		const url = link.indexOf("?") != -1 ? link.split("?")[0] : link,
			_url = link.split("://")[1];
		setTimeout(() => {
			onAlipayTo(_url);
		}, 600)
	}
}

//保存场景值
export const saveUserVisitScene = () => {
	setTimeout(() => {
		if (getScene() != undefined && !!getUserId()) {
			request("member/mall/aliPay/userVisitCode/addUserVisitCode", {
				'uid': getUserId(),
				'code': getScene()
			}, "POST").then((res) => {})
		}
	}, 500);
}


/***
 * 节流函数 在wait间隔时间内不再进行任何调用时，触发一次最后的调用（如:wait设置为300ms，一直点击，该函数一直不执行，只有在间隔了300ms不做任何点击后，才执行刚才的最后一次点击）
 * @ func 执行函数
 * @ wait 等待时间
 * @ {Boolean} immediate 是否立即执行
 * @return {Function}
 */
export const throttle0 = (func, wait, immediate) => {
	var timeout;
	return function() {
		let context = this;
		let args = arguments;
		let later = function() {
			timeout = null;
			if (!immediate) func.apply(context, args)
		}
		let callNow = immediate && !timeout;
		clearTimeout(timeout);
		timeout = setTimeout(later, wait);
		if (callNow) func.apply(context, args)
	}
}



// 防抖
export const debounce = (fn, delay) => {
	var time = null
	return function() {
		let context = this; //记录一下this指向
		let args = arguments;
		//清除定时任务
		if (time) clearTimeout(time);
		time = setTimeout(function() {
			time = null;
			fn.apply(context, args)
		}, delay)
	}
}
// ps:！！！！！！！！防抖扩展---第三个参数控制第一次点击是否立即执行，
// export const debounce = (fn, delay, immediate) => {
// 	var time = null
// 	return function() {
// 		let context = this;//记录一下this指向
// 		let args = arguments;
// 		//清除定时任务
// 		if (time) clearTimeout(time);
// 		// 第一次点击是否立即执行
// 		if (immediate) {
// 			fn.apply(context, args)
// 			immediate = false;

// 			// 超过delay时间immediate重置为true 
// 			time = setTimeout(function() {
// 				time = null;
// 				immediate = true;
// 			}, delay)
// 		} else {
// 			time = setTimeout(function() {
// 				time = null;
// 				fn.apply(context, args)
// 			}, delay)
// 		}
// 	}
// }

// 节流

export const throttle = (fn, delay) => {
	// 时间戳
	var timeTwo = 0 //new Date();
	// 定时器
	var timeThree = null;
	return function() {
		let context = this;
		let args = arguments;
		var now = new Date()

		// 结合 ps:最后一次触发在固定频率内会在延迟后触发
		var wait = delay - (now - timeTwo)
		clearTimeout(timeThree)
		if (wait <= 0) {
			fn.apply(context, args);
			timeTwo = new Date();
		} else {
			timeThree = setTimeout(function() {
				fn.apply(context, args);
			}, delay)
		}
	}
}

export function getMobileSys() {
	//判断是ios端还是android端
	var userAgent = navigator.userAgent;
	var isAndroid = userAgent.indexOf('Android') > -1 || userAgent.indexOf('Adr') > -1; //android终端
	var isIOS = !!userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
	//false为android终端
	//true为ios终端
	if (isAndroid) {
		//是安卓手机
		return 'Android';
	} else if (isIOS) {
		//是ios手机
		return 'IOS';
	}
}

export function getUserIp() {
	uni.request({
		url: 'https://api.ipify.org', // 这是一个提供获取客户端公网IP服务的简单API
		method: 'GET',
		success: (res) => {
			const ip = res.data
			console.log('当前设备公网IP地址：', ip);
			uni.setStorage({
				key: 'userIp',
				data: ip
			});
		},
		fail: (err) => {
			console.error('获取IP地址失败：', err);
		}
	});
}


// 计算出时间戳的具体数据：比如将85400转化为 n天n时n分n秒
/** 
1、js获取 倒计时 天时分秒
通过时间戳的方式来 
 let d =  parseInt(dec / 60 / 60 / 24); // 天
 let h =  parseInt(dec / 60 / 60 % 24); // 时
 let m =  parseInt(dec / 60 % 60); // 分
 let s =  parseInt(dec % 60); // 秒
 2、参数分析:
 @params {Num} inputTime: 需要转换成 天时分秒 的 13位时间戳
 @params {Boolean} isPop: 便于实现两种返回结果：true -> `${d}天${h}小时${m}分${s}秒` ; false -> 包含天时分秒的finalDateObj对象
 */
export function formateTimeStamp(inputTime, isPop = true) {
	// console.log('要倒计时的时间戳',inputTime);
	// 最终时间结果对象
	const finalDateObj = {
		d: null, // 天
		h: null, // 小时
		m: null, // 分钟
		s: null, // 秒
	}

	// 剩余时间总的毫秒数 除以 1000 变为总秒数（时间戳为13位 需要除以1000，为10位 则不需要）
	let dec = inputTime / 1000;

	if (dec <= 0) {
		dec = 0;
	}

	// 得到天 格式化成前缀加零的样式
	let d = parseInt(dec / 60 / 60 / 24);
	d = d < 10 ? '0' + d : d;
	// 得到小时 格式化成前缀加零的样式
	let h = parseInt(dec / 60 / 60 % 24);
	h = h < 10 ? '0' + h : h;
	// 得到分钟 格式化成前缀加零的样式
	let m = parseInt(dec / 60 % 60);
	m = m < 10 ? '0' + m : m;
	// 得到秒 格式化成前缀加零的样式
	let s = parseInt(dec % 60);
	s = s < 10 ? '0' + s : s;

	finalDateObj.d = d;
	finalDateObj.h = h;
	finalDateObj.m = m;
	finalDateObj.s = s;

	return isPop ? `${d}天${h}小时${m}分${s}秒` : finalDateObj;

}


export function jumpAntESign(flowIds, signerIds) {

	let env = 'prod'
	let flowId = flowIds
	let signerId = signerIds
	let skipResult = true
	let skipGuide = false

	my.navigateTo({
		url: `plugin://esign/esign?env=${env}&flowId=${flowId}&signerId=${signerId}&skipResult=${skipResult}&skipGuide=${skipGuide}`,
	})

}